package com.xinmao.quantitative.trad.strategies.combine;

import com.xinmao.quantitative.trad.strategies.IStrategy;
import org.springframework.stereotype.Component;
import org.ta4j.core.BarSeries;
import org.ta4j.core.BaseStrategy;
import org.ta4j.core.Rule;
import org.ta4j.core.Strategy;
import org.ta4j.core.indicators.EMAIndicator;
import org.ta4j.core.indicators.RSIIndicator;
import org.ta4j.core.indicators.StochasticOscillatorDIndicator;
import org.ta4j.core.indicators.StochasticOscillatorKIndicator;
import org.ta4j.core.indicators.helpers.ClosePriceIndicator;
import org.ta4j.core.indicators.helpers.VolumeIndicator;
import org.ta4j.core.indicators.volume.MoneyFlowIndexIndicator;
import org.ta4j.core.num.DecimalNum;
import org.ta4j.core.num.Num;
import org.ta4j.core.rules.*;

/**
 Stochastic Oscillator（随机震荡指标）是一种技术分析工具，用于帮助交易者判断市场的超买和超卖情况，以及确定价格反转的潜在时机。以下是关于Stochastic Oscillator的详细介绍：

 一、定义与计算
 定义：Stochastic Oscillator，又称随机震荡指标，英文简称为KDJ，理论基础为“随机漫步”理论，属于动量类的技术指标。它可以帮助判断市场趋势和过度买卖情况。
 计算：该指标的计算涉及最高价、最低价和收盘价。具体计算步骤如下：
 首先，计算一段时间（通常为某个特定周期，例如9天、14天等）内的最高价(Hn)和最低价(Ln)。
 接着，计算收盘价(Ct)在这段时间内的百分比位置，即RSV（未成熟随机值）=[(Ct-Ln)/(Hn-Ln)] ×100。
 然后，对RSV进行平滑处理，得到K值（快线），通常是以一定周期（如3天）内的RSV的移动平均值来计算。
 最后，对K值再进行一次平滑处理，得到D值（慢线），通常是K值的移动平均值。
 二、应用与分析
 1.判断超买超卖：当K值或D值超过80时，市场可能处于超买状态，价格有可能出现回调或反转；当K值或D值低于20时，市场可能处于超卖状态，价格有可能出现反弹。
 2.交叉信号：当K线上穿D线时，是一个买入信号；当K线下穿D线时，是一个卖出信号。
 3.背离判断：当市场价格创新高（或新低），而Stochastic Oscillator指标并未创新高（或新低）时，可能发生顶背离（或底背离），这是价格可能反转的信号。
 三、优缺点
 优点：反应灵敏，能够及时捕捉到市场的短期波动。
 缺点：容易钝化，在市场趋势来临时可能失效，从而错失大行情。
 总的来说，Stochastic Oscillator是一种有效的技术分析工具，但应与其他指标和分析方法结合使用以提高准确性。同时，由于市场情况千变万化，投资者在使用时应根据实际情况灵活调整参数和判断标准。
 * */
@Component
public class StochasticOscillKDStrategy implements IStrategy {

    @Override
    public Strategy buildStrategy(BarSeries series) {
        if (series == null) {
            throw new IllegalArgumentException("Series cannot be null");
        }

        ClosePriceIndicator closePrice = new ClosePriceIndicator(series);

        StochasticOscillatorKIndicator stochasticOscillK = new StochasticOscillatorKIndicator(series, 14);
        StochasticOscillatorDIndicator stochasticOscillD = new StochasticOscillatorDIndicator(stochasticOscillK);


        EMAIndicator ema5 = new EMAIndicator(closePrice, 5);
        EMAIndicator ema8 = new EMAIndicator(closePrice, 8);



        RSIIndicator rsi = new RSIIndicator(closePrice, 2);

        MoneyFlowIndexIndicator mfi = new MoneyFlowIndexIndicator(series, 14);
        // Entry rule
        // 短期EMA上穿长期EMA（表示趋势向上）。
        // 随机振荡器K指标下穿20线（可能是一个买入信号）。
        // MACD上穿其EMA（可能是另一个买入信号）
        Rule entryRule = new UnderIndicatorRule(stochasticOscillK, 20)
                .and(new CrossedUpIndicatorRule(stochasticOscillK, stochasticOscillD));

        // Exit rule
        // MACD下穿其EMA（可能是另一个卖出信号）。
        Rule exitRule = (new OverIndicatorRule(stochasticOscillK, 80)
                .and(new CrossedDownIndicatorRule(stochasticOscillK, stochasticOscillD)));

        return new BaseStrategy(entryRule, exitRule);
    }

    @Override
    public Num getScore() {
        //1.4
        return DecimalNum.valueOf(1);
    }
}
